/**
 ******************************************************************************
 * @file    FW_upgrade/src/usbh_usr.c
 * @author  MCD Application Team
 * @version V1.0.0
 * @date    28-October-2011
 * @brief   This file includes the usb host user callbacks
 ******************************************************************************
 * @attention
 *
 * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
 * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
 * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
 * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
 * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
 * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
 *
 * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
 ******************************************************************************
 */

/* Includes ------------------------------------------------------------------*/
#include "usbh_usr.h"
#include"ff.h"
//#include"ff.h"

/** @addtogroup STM32F4-Discovery_FW_Upgrade
 * @{
 */

/* Private typedef -----------------------------------------------------------*/
/* Private defines -----------------------------------------------------------*/
/* Private macros ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/*  Points to the DEVICE_PROP structure of current device */
/*  The purpose of this register is to speed up the execution */

USBH_Usr_cb_TypeDef USR_Callbacks = { USBH_USR_Init, USBH_USR_DeInit,
		USBH_USR_DeviceAttached, USBH_USR_ResetDevice,
		USBH_USR_DeviceDisconnected, USBH_USR_OverCurrentDetected,
		USBH_USR_DeviceSpeedDetected, USBH_USR_Device_DescAvailable,
		USBH_USR_DeviceAddressAssigned, USBH_USR_Configuration_DescAvailable,
		USBH_USR_Manufacturer_String, USBH_USR_Product_String,
		USBH_USR_SerialNum_String, USBH_USR_EnumerationDone, USBH_USR_UserInput,
		USBH_USR_MSC_Application, USBH_USR_DeviceNotSupported,
		USBH_USR_UnrecoveredError };

FATFS fatfs;
FIL file;
FIL fileR;
DIR dir;
FILINFO fno;
UINT BytesRead;
uint16_t buffer1[_MAX_SS] = { 0x00 };

static uint8_t USBH_USR_ApplicationState = USH_USR_FS_INIT;
extern USB_OTG_CORE_HANDLE USB_OTG_Core;
__IO uint32_t TimingDelay;
__IO uint32_t UploadCondition = 0x00;

/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/**
 * @brief  USBH_USR_Init
 *         Displays the message on LCD for host lib initialization
 * @param  None
 * @retval None
 */
void USBH_USR_Init(void) {
	static uint8_t startup = 0;

	if (startup == 0) {
		startup = 1;
		/* Initialize LEDs and Push_Button on STM32F4-Discovery**************************/
		// STM_EVAL_LEDInit(LED3);
		//  STM_EVAL_LEDInit(LED4);
		//  STM_EVAL_LEDInit(LED5);
		/// STM_EVAL_LEDInit(LED6);
		//  STM_EVAL_PBInit(BUTTON_USER, BUTTON_MODE_GPIO);
	}

	/* Setup SysTick Timer for 1 msec interrupts.
	 ------------------------------------------
	 1. The SysTick_Config() function is a CMSIS function which configure:
	 - The SysTick Reload register with value passed as function parameter.
	 - Configure the SysTick IRQ priority to the lowest value (0x0F).
	 - Reset the SysTick Counter register.
	 - Configure the SysTick Counter clock source to be Core Clock Source (HCLK).
	 - Enable the SysTick Interrupt.
	 - Start the SysTick Counter.

	 2. You can change the SysTick Clock source to be HCLK_Div8 by calling the
	 SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8) just after the
	 SysTick_Config() function call. The SysTick_CLKSourceConfig() is defined
	 inside the misc.c file.

	 3. You can change the SysTick IRQ priority by calling the
	 NVIC_SetPriority(SysTick_IRQn,...) just after the SysTick_Config() function
	 call. The NVIC_SetPriority() is defined inside the core_cm4.h file.

	 4. To adjust the SysTick time base, use the following formula:

	 Reload Value = SysTick Counter Clock (Hz) x  Desired Time base (s)

	 - Reload Value is the parameter to be passed for SysTick_Config() function
	 - Reload Value should not exceed 0xFFFFFF
	 */
	if (SysTick_Config(SystemCoreClock / 1000)) {
		/* Capture error */
		while (1)
			;
	}
}

/**
 * @brief  USBH_USR_DeviceAttached
 *         Displays the message on LCD on device attached
 * @param  None
 * @retval None
 */
void USBH_USR_DeviceAttached(void) {
	printf("\r\ndevice attached !");
}

/**
 * @brief  USBH_USR_UnrecoveredError
 * @param  None
 * @retval None
 */
void USBH_USR_UnrecoveredError(void) {
	/* Toggle Red LED in infinite loop */
	Fail_Handler();
}

/**
 * @brief  USBH_DisconnectEvent
 *         Device disconnect event
 * @param  None
 * @retval Staus
 */
void USBH_USR_DeviceDisconnected(void) {
	/* Toggle Red LED in infinite loop: USB device disconnected */
	Fail_Handler();
}

/**
 * @brief  USBH_USR_ResetUSBDevice
 * @param  None
 * @retval None
 */
void USBH_USR_ResetDevice(void) {
	/* callback for USB-Reset */
}

/**
 * @brief  USBH_USR_DeviceSpeedDetected
 *         Displays the message on LCD for device speed
 * @param  Device speed:
 * @retval None
 */
void USBH_USR_DeviceSpeedDetected(uint8_t DeviceSpeed) {
	if ((DeviceSpeed != HPRT0_PRTSPD_FULL_SPEED)
			&& (DeviceSpeed != HPRT0_PRTSPD_LOW_SPEED)) {
		/* Toggle Red LED in infinite loop: USB device disconnected */
		Fail_Handler();
	}
}

/**
 * @brief  USBH_USR_Device_DescAvailable
 * @param  device descriptor
 * @retval None
 */
// uint8_t   bLength;
//   uint8_t   bDescriptorType;
//   uint16_t  bcdUSB;        /* USB Specification Number which device complies too */
//   uint8_t   bDeviceClass;
//   uint8_t   bDeviceSubClass; 
//   uint8_t   bDeviceProtocol;
//   /* If equal to Zero, each interface specifies its own class
//   code if equal to 0xFF, the class code is vendor specified.
//   Otherwise field is valid Class Code.*/
//   uint8_t   bMaxPacketSize;
//   uint16_t  idVendor;      /* Vendor ID (Assigned by USB Org) */
//   uint16_t  idProduct;     /* Product ID (Assigned by Manufacturer) */
//   uint16_t  bcdDevice;     /* Device Release Number */
//   uint8_t   iManufacturer;  /* Index of Manufacturer String Descriptor */
//   uint8_t   iProduct;       /* Index of Product String Descriptor */
//   uint8_t   iSerialNumber;  /* Index of Serial Number String Descriptor */
//   uint8_t   bNumConfigurations; /* Number of Possible Configurations */
//xuat thong tin usb
void USBH_USR_Device_DescAvailable(void *DeviceDesc) {
	USBH_DevDesc_TypeDef *hs;
	hs = DeviceDesc;
	fprintf1("\r\n =============== DESCRIPTOR =============== ");
	fprintf1("\r\n Name               \t Value ");
	fprintf1("\r\n ==========================================");
//  char c= hs->bLength''
	fprintf1("\r\n bLength            \t %x", hs->bLength);
	fprintf1(USART2, "\r\n bDescriptorType    \t %x", hs->bDescriptorType);
	fprintf1("\r\n bcdUSB             \t %x", hs->bcdUSB);
	fprintf1("\r\n bDeviceClass       \t %x", hs->bDeviceClass);
	fprintf1("\r\n bDeviceSubClass    \t %x", hs->bDeviceSubClass);
	fprintf1("\r\n bDeviceProtocol    \t %x", hs->bDeviceProtocol);
	fprintf1("\r\n bMaxPacketSize     \t %x", hs->bMaxPacketSize);
	fprintf1("\r\n idVendor           \t %x", hs->idVendor);
	fprintf1("\r\n idProduct          \t %x", hs->idProduct);
	fprintf1("\r\n bcdDevice          \t %x", hs->bcdDevice);
	fprintf1("\r\n iManufacturer      \t %x", hs->iManufacturer);
	fprintf1("\r\n iProduct           \t %x", hs->iProduct);
	fprintf1("\r\n iSerialNumber      \t %x", hs->iSerialNumber);
	fprintf1("\r\n bNumConfigurations \t %x", hs->iSerialNumber);
	fprintf1(" \r\n");
	/* callback for device descriptor */
}
char buffer[50];
void USART_puts1(USART_TypeDef *USARTx, volatile char *s) {
	while (*s) {
		while (!(USARTx->SR && 0x00000040))
			;
		USART_SendData(USARTx, *s);
		*s++;

	}
}

/**
 * @brief  Retargets the C library printf function to the USART.
 * @param  None
 * @retval None
 */
/**
 * @brief  USBH_USR_DeviceAddressAssigned
 *         USB device is successfully assigned the Address
 * @param  None
 * @retval None
 */
void USBH_USR_DeviceAddressAssigned(void) {
	/* callback for device successfully assigned the Address */
}

/**
 * @brief  USBH_USR_Conf_Desc
 * @param  Configuration descriptor
 * @retval None
 */

// typedef struct _ConfigurationDescriptor
// {
//   uint8_t   bLength;
//   uint8_t   bDescriptorType;
//   uint16_t  wTotalLength;        /* Total Length of Data Returned */
//   uint8_t   bNumInterfaces;       /* Number of Interfaces */
//   uint8_t   bConfigurationValue;  /* Value to use as an argument to select this configuration*/
//   uint8_t   iConfiguration;       /*Index of String Descriptor Describing this configuration */
//   uint8_t   bmAttributes;         /* D7 Bus Powered , D6 Self Powered, D5 Remote Wakeup , D4..0 Reserved (0)*/
//   uint8_t   bMaxPower;            /*Maximum Power Consumption */
// }
// typedef struct _InterfaceDescriptor
// {
//   uint8_t bLength;
//   uint8_t bDescriptorType;
//   uint8_t bInterfaceNumber;
//   uint8_t bAlternateSetting;    /* Value used to select alternative setting */
//   uint8_t bNumEndpoints;        /* Number of Endpoints used for this interface */
//   uint8_t bInterfaceClass;      /* Class Code (Assigned by USB Org) */
//   uint8_t bInterfaceSubClass;   /* Subclass Code (Assigned by USB Org) */
//   uint8_t bInterfaceProtocol;   /* Protocol Code */
//   uint8_t iInterface;           /* Index of String Descriptor Describing this interface */
//   
// }
// USBH_InterfaceDesc_TypeDef;
// typedef struct _EndpointDescriptor
// {
//   uint8_t   bLength;
//   uint8_t   bDescriptorType;
//   uint8_t   bEndpointAddress;   /* indicates what endpoint this descriptor is describing */
//   uint8_t   bmAttributes;       /* specifies the transfer type. */
//   uint16_t  wMaxPacketSize;    /* Maximum Packet Size this endpoint is capable of sending or receiving */  
//   uint8_t   bInterval;          /* is used to specify the polling interval of certain transfers. */
// }
// USBH_EpDesc_TypeDef;
void USBH_USR_Configuration_DescAvailable(USBH_CfgDesc_TypeDef * cfgDesc,
		USBH_InterfaceDesc_TypeDef *itfDesc, USBH_EpDesc_TypeDef *epDesc) {

	fprintf1("\r\n");
	fprintf1("\r\n================= CONFIGURATION ==================");

	fprintf1("\r\n Name                 \t\t  Value");
	fprintf1("\r\n===================================================");
	fprintf1("\r\n bLength              \t\t  %x", cfgDesc->bLength);
	fprintf1("\r\n bDescriptorType      \t\t  %x", cfgDesc->bDescriptorType);
	fprintf1("\r\n wTotalLength         \t\t  %x", cfgDesc->wTotalLength);
	fprintf1("\r\n bNumInterfaces       \t\t  %x", cfgDesc->bNumInterfaces);
	fprintf1("\r\n bConfigurationValue  \t\t  %x",
			cfgDesc->bConfigurationValue);
	fprintf1("\r\n iConfiguration       \t\t  %x", cfgDesc->iConfiguration);
	fprintf1("\r\n bmAttributes         \t\t  %x", cfgDesc->bmAttributes);
	fprintf1("\r\n bMaxPower            \t\t  %x", cfgDesc->bMaxPower);

	fprintf1("\r\n");
	fprintf1("\r\n================= INTERFACEDESCRIPTOR ==================");

	fprintf1("\r\n Name                 \t\t  Value");
	fprintf1("\r\n===================================================");
	fprintf1("\r\n bLength              \t\t  %x", itfDesc->bLength);
	fprintf1("\r\n bDescriptorType      \t\t  %x", itfDesc->bDescriptorType);
	fprintf1("\r\n bInterfaceNumber     \t\t  %x", itfDesc->bInterfaceNumber);
	fprintf1("\r\n bAlternateSetting    \t\t  %x", itfDesc->bAlternateSetting);
	fprintf1("\r\n bNumEndpoints        \t\t  %x", itfDesc->bNumEndpoints);
	fprintf1("\r\n bInterfaceClass      \t\t  %x", itfDesc->bInterfaceClass);
	fprintf1("\r\n bInterfaceSubClass   \t\t  %x", itfDesc->bInterfaceSubClass);
	fprintf1("\r\n bInterfaceProtocol   \t\t  %x", itfDesc->bInterfaceProtocol);
	fprintf1("\r\n iInterface           \t\t  %x", itfDesc->iInterface);

	fprintf1("\r\n");
	fprintf1("\r\n================= ENDPOINT ==================");

	fprintf1("\r\n Name                 \t\t  Value");
	fprintf1("\r\n===================================================");
	fprintf1("\r\n bLength              \t\t  %x", epDesc->bLength);
	fprintf1("\r\n bDescriptorType      \t\t  %x", epDesc->bDescriptorType);
	fprintf1("\r\n bEndpointAddress     \t\t  %x", epDesc->bEndpointAddress);
	fprintf1("\r\n bmAttributes         \t\t  %x", epDesc->bmAttributes);
	fprintf1("\r\n wMaxPacketSize       \t\t  %x", epDesc->wMaxPacketSize);
	fprintf1("\r\n bInterval            \t\t  %x", epDesc->bInterval);

	fprintf1("\r\n");

	/* callback for configuration descriptor */
}

/**
 * @brief  USBH_USR_Manufacturer_String
 * @param  Manufacturer String
 * @retval None
 */

void USBH_USR_Manufacturer_String(void *ManufacturerString) {
	/* callback for  Manufacturer String */
}

/**
 * @brief  USBH_USR_Product_String
 * @param  Product String
 * @retval None
 */
void USBH_USR_Product_String(void *ProductString) {
	/* callback for Product String */
}

/**
 * @brief  USBH_USR_SerialNum_String
 * @param  SerialNum_String
 * @retval None
 */
void USBH_USR_SerialNum_String(void *SerialNumString) {
	/* callback for SerialNum_String */
}

/**
 * @brief  EnumerationDone
 *         User response request is displayed to ask application jump to class
 * @param  None
 * @retval None
 */
void USBH_USR_EnumerationDone(void) {
	USB_OTG_BSP_mDelay(500);

	USBH_USR_MSC_Application();
}

/**
 * @brief  USBH_USR_DeviceNotSupported
 *         Device is not supported
 * @param  None
 * @retval None
 */
void USBH_USR_DeviceNotSupported(void) {
	/* Toggle Red LED in infinite loop */
	Fail_Handler();
}

/**
 * @brief  USBH_USR_UserInput
 *         User Action for application state entry
 * @param  None
 * @retval USBH_USR_Status : User response for key button
 */
USBH_USR_Status USBH_USR_UserInput(void) {
	/* callback for Key botton: set by software in this case */
	return USBH_USR_RESP_OK;
}

/**
 * @brief  USBH_USR_OverCurrentDetected
 *         Over Current Detected on VBUS
 * @param  None
 * @retval None
 */
void USBH_USR_OverCurrentDetected(void) {
}

/**
 * @brief  USBH_USR_MSC_Application
 *         Demo application for IAP thru USB mass storage
 * @param  None
 * @retval Staus
 */

int USBH_USR_MSC_Application(void) {

	switch (USBH_USR_ApplicationState) {
	case USH_USR_FS_INIT:

		/* Initialises the File System*/
		if (f_mount(0, &fatfs) != FR_OK) {
			/* efs initialisation fails*/
			return (-1);
		}

		/* Flash Disk is write protected */
		if (USBH_MSC_Param.MSWriteProtect == DISK_WRITE_PROTECTED) {
			while (1) {
				/* Red LED On */
				//     STM_EVAL_LEDOn(LED5);
			}
		}
		/* Go to menu */
		USBH_USR_ApplicationState = USH_USR_IAP;
		break;

	case USH_USR_IAP:

		/* Go to Audio menu */
//		COMMAND_AudioExecuteApplication();
		COMMAND_DIRExecuteApplication();
		/* Set user initialization flag */
		USBH_USR_ApplicationState = USH_USR_TEXT;
///		USBH_USR_ApplicationState=
		break;
	case USH_USR_DIR:

		/* Go to Audio menu */
		//COMMAND_AudioExecuteApplication();

		/* Set user initialization flag */
		USBH_USR_ApplicationState = USH_USR_TEXT;
///		USBH_USR_ApplicationState=
		break;

	default:
		break;
	}
	return (0);
}
FRESULT scan_files (
    char* path        /* Start node to be scanned (also used as work area) */
)
{
    FRESULT res;
    FILINFO fno;
    DIR dir;
    int i;
    char *fn;   /* This function is assuming non-Unicode cfg. */
#if _USE_LFN
    static char lfn[_MAX_LFN + 1];
    fno.lfname = lfn;
    fno.lfsize = sizeof lfn;
#endif


    res = f_opendir(&dir, path);                       /* Open the directory */
    if (res == FR_OK) {
        i = strlen(path);
        for (;;) {
            res = f_readdir(&dir, &fno);                   /* Read a directory item */

            if (res != FR_OK || fno.fname[0] == 0)
            	break;  /* Break on error or end of dir */
//            fprintf1("%s\n", fno.fname);

            if (fno.fname[0] == '.')
            	continue;             /* Ignore dot entry */
#if _USE_LFN
            fn = *fno.lfname ? fno.lfname : fno.fname;
#else
            fn = fno.fname;
#endif
            if (fno.fattrib & AM_DIR) {                    /* It is a directory */
                sprintf(&path[i], "/%s", fn);
                fprintf1("%s/\n", path);
                //res = scan_files(path);
               // fprintf1("%s/%s\n", path, fn);
                if (res != FR_OK) break;
                path[i] = 0;
            } else {                                       /* It is a file. */
                fprintf1("%s", path);
            }
            fprintf1("\n");

        }
    }

    return res;
}
COMMAND_DIRExecuteApplication() {
	char path[] = "0:/";
	if (f_opendir(&dir, path) != FR_OK) {
			while (1) {
				//   STM_EVAL_LEDToggle(LED5);
				Delay(10);
			}
		}
	FRESULT	res= scan_files(path);
				 //for(i=0;i< fno.fattrib;i++)
					//	fprintf1("%c", (char)fno.fname[i]);
				//fprintf1("\n");
	//			for(i=0; i<BytesRead; i++)
	//				putchar(Buffer[i]);

			//}
		//	res = f_close(&fileR);

	//FILINFO fno;
	//f_opendir (DIR*, const XCHAR*);
}

COMMAND_AudioExecuteApplication() {

	WavePlayerStart();
}
//int flag = 0;
void WavePlayerStart(void) {
	char path[] = "0:/";
//	LED_Init();
//	LED_On(2);

	//buffer_switch = 1;

	/* Get the read out protection status */
	if (f_opendir(&dir, path) != FR_OK) {
		while (1) {
			//   STM_EVAL_LEDToggle(LED5);
			Delay(10);
		}
	}

//	dir->dir
	/* Open the wave file to be played */
	if (f_open(&fileR, "message.txt", FA_READ) != FR_OK) {
		// STM_EVAL_LEDOn(LED5);
		// Command_index = 1;
	} else {
	//	if (flag == 0) {
			UINT Total = 0;
			FRESULT res;

			/* Read data(_MAX_SS byte) from the selected file */
			while (1) {
				BYTE Buffer[512];
							UINT BytesRead;
							UINT i;

				res = f_read(&fileR, Buffer, sizeof(Buffer), &BytesRead);

	//			if (res != FR_OK)
	//				printf("res = %d f_read MESSAGE.TXT\n", res);

				if (res != FR_OK)
					break;

				Total += BytesRead;
				for (i = 0; i < BytesRead; i++)
					fprintf1("%c", (char)Buffer[i]);
				fprintf1("\n");

	//			for(i=0; i<BytesRead; i++)
	//				putchar(Buffer[i]);

				if (BytesRead < sizeof(Buffer))
					break;
			}
			res = f_close(&fileR);
		//}
		//flag = 1;


		LED_Init();
		LED_On(2);

		// WaveFileStatus = WavePlayer_WaveParsing(&wavelen);

		//if (WaveFileStatus == Valid_WAVE_File)  /* the .WAV file is valid */
		//{
		/* Set WaveDataLenght to the Speech wave length */
		//WaveDataLength = WAVE_Format.DataSize;
//      //}
//      else /* Unvalid wave file */
//      {
//        /* Led Red Toggles in infinite loop */
//        while(1)
//        {
//          STM_EVAL_LEDToggle(LED5);
//          Delay(10);
//        }
//      }
//      /* Play the wave */
//      WavePlayBack(WAVE_Format.SampleRate);
//    }
	}
}
void fprintf1(char *c) {
	sprintf(buffer, c);
	USART_puts1(USART2, buffer);

}

/**
 * @brief  USBH_USR_DeInit
 *         Deint User state and associated variables
 * @param  None
 * @retval None
 */
void USBH_USR_DeInit(void) {
	USBH_USR_ApplicationState = USH_USR_FS_INIT;
}

/**
 * @brief  This function handles the program fail.
 * @param  None
 * @retval None
 */
void Fail_Handler(void) {
	while (1) {
		/* Toggle Red LED */
		//STM_EVAL_LEDToggle(LED5);
		Delay(50);
	}
}

/**
 * @brief  Inserts a delay time.
 * @param  nTime: specifies the delay time length, in milliseconds.
 * @retval None
 */
void Delay(__IO uint32_t nTime) {
	TimingDelay = nTime;

	while (TimingDelay != 0)
		;
}

/**
 * @brief  Decrements the TimingDelay variable.
 * @param  None
 * @retval None
 */
void TimingDelay_Decrement(void) {
	if (TimingDelay != 0x00) {
		TimingDelay--;
	}
}

/**
 * @}
 */

/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
